package org.stvd.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.stvd.core.util.LogUtil;

/**
 * @Title: FileUtil
 * @Description 文件工具类
 * @author houzx
 * @date 2020年10月17日
 */
public class FileUtil {

    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
    
    /**
     * 给文件重命名 防止覆盖
     * @param fileName
     * @return 时间戳+原始文件的后缀
     */
    public static String reName(String fileName){
        return new StringBuffer().append(IdWorker.getInstance().nextId()).append(fileName.substring(fileName.indexOf("."))).toString();
    }
    
    /**
     * 文件名称验证
     * @param filename 文件名称
     * @return true 正常 false 非法
     */
    public static boolean isValidFilename(String filename) {
        return filename.matches(FILENAME_PATTERN);
    }
    
    /**
     * 写入流到本地文件
     * @param filePath 文件路径
     * @param is 输入流
     * @return
     */
    public static void writeToLocal(String filePath, InputStream is) throws IOException {
        FileOutputStream fos = null;
        try {
            int index;
            byte[] bytes = new byte[1024];
            fos = new FileOutputStream(filePath);
            while ((index = is.read(bytes)) != -1) {
                fos.write(bytes, 0, index);
                fos.flush();
            }
        } catch (IOException e){
            throw e;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 输出指定文件的byte数组
     * @param filePath 文件路径
     * @param os 输出流
     * @return
     */
    public static void writeToBytes(String filePath, OutputStream os) throws IOException {
        FileInputStream fis = null;
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0) {
                os.write(b, 0, length);
            }
        } catch (IOException e){
            throw e;
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
    
    /**
     * 删除文件
     * @param filePath 文件
     * @return
     */
    public static boolean deleteFile(String filePath){
        boolean flag = false;
        File file = new File(filePath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 下载文件名重新编码
     * @param request 请求对象
     * @param fileName 文件名
     * @return 编码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName)
            throws UnsupportedEncodingException {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }else if (agent.contains("Firefox")) {
            // 火狐浏览器
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }else if (agent.contains("Chrome")) {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
    
    /**
     * 复制文件从一个文件夹到另一个文件夹
     * @param oldPath 原文件路径
     * @param newfile 新文件路径
     * @param fileName 文件名称
     * @return
     */
    @SuppressWarnings("resource")
    public static String copyFile(String oldPath, String newfile,String fileName) { 
        String returnMsg = null;
       try { 
           int byteread = 0; 
           File oldfile = new File(oldPath); 
           if (oldfile.exists()) {//文件存在时 
               InputStream inStream = new FileInputStream(oldPath);//读入原文件 
               String localPath = oldPath.substring(0,oldPath.indexOf("/assets"));
               localPath = localPath + newfile;
               if (!(new File(localPath).isDirectory())) {
                    new File(localPath).mkdirs();
                   }
               FileOutputStream fs = new FileOutputStream(localPath+"/"+fileName); 
               byte[] buffer = new byte[1444]; 
               while ( (byteread = inStream.read(buffer)) != -1) { 
                   fs.write(buffer, 0, byteread); 
               } 
               inStream.close(); 
           }else{
               returnMsg ="上传文件不存在！"; 
           }
       }  catch (Exception e) { 
           returnMsg ="复制文件错误！"; 
           e.printStackTrace(); 
       } 
       return returnMsg;
   } 
    
    /**
     * 文件下载
     * @param request
     * @param response
     * @param FileUri 要下载的文件的绝对路径[必须]
     * @param fileType 要下载的文件的类型：用以设置response的contentType
     * @throws IOException
     */
    public static void downFile(HttpServletRequest request,HttpServletResponse response,
        String fileUri, String fileType) throws IOException {
        if (fileUri==null || "".equals(fileUri)) {
            return ;
        }

        // 要下载的文件
        File templateFile = new File(fileUri);
        if (!templateFile.exists()) {
            return;
        }

        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(templateFile);
            response.setContentType("application/x-download; charset=utf-8");
            response.setHeader("Content-disposition", "attachment;filename="
                    + java.net.URLEncoder.encode(templateFile.getName(), "UTF-8"));
            if (fileType!=null && !"".equals(fileType)) {
                response.setContentType(fileType); //定义输出类型
            }
            outputStream = response.getOutputStream();
            byte[] b = new byte[1024];
            int length;
            while ((length = inputStream.read(b)) > 0) {
                outputStream.write(b, 0, length);
            }
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }
    
    /**
     * 压缩多个文件成一个zip文件
     * @param fileList 源文件列表
     * @param filePath 压缩后文件保存路径
     * @param fileName 压缩后文件保存名称
     * @return true/false
     * @throws IOException
     */
    public static boolean zipFiles(List<File> fileList, String filePath, String fileName) throws IOException{
        boolean zipFlag = false;
        byte[] buf=new byte[10240];  
        ZipOutputStream out = null;
        FileInputStream in = null;
        
        File zipFilePath = new File(filePath);
        if (!zipFilePath.exists())
            zipFilePath.mkdirs();
        
        File zipFile = new File(filePath + fileName);
        if(!zipFile.exists()){
            zipFile.createNewFile();
        }
        
        try {  
            //ZipOutputStream类：完成文件或文件夹的压缩  
            out=new ZipOutputStream(new FileOutputStream(zipFile));  
            //注意此处编码设置
            out.setEncoding("utf-8");
            for(int i=0, n = fileList.size(); i < n; i++){  
                in = new FileInputStream(fileList.get(i));  
                out.putNextEntry(new ZipEntry(fileList.get(i).getName()));  
                int len;  
                while((len=in.read(buf))>0){  
                    out.write(buf,0,len);  
                }  
                out.closeEntry();  
                in.close();  
                in = null;
            }  
            out.close();  
            out = null;
            zipFlag = true;
            LogUtil.info("压缩完成,文件详细信息为：" + zipFile.getAbsolutePath());
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally{
            if(in!=null){
                try {
                    in.close();
                    in = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(out!=null){
                try {
                    out.close();
                    out = null;
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return zipFlag;
    }
}
